#include "shape.h"


Shape::Shape(const QPoint &h, const vector<vector<QPoint> > &ord)
{
    this->head = h;
    this->order = ord;
    this->iter = this->order.begin();
}

Shape::Shape(const Shape &s)
{
    this->head = s.head;
    this->order = s.order;
    this->iter = this->order.begin();
}

Shape &Shape::downStep()
{
    this->head+=QPoint(0,1);
    return *this;
}

Shape &Shape::leftStep()
{
    this->head+=QPoint(-1,0);
    return *this;
}

Shape &Shape::rightStep()
{
    this->head+=QPoint(1,0);
    return *this;
}

QPoint Shape::getHead() const
{
    return this->head;
}

vector<QPoint> Shape::getCurIter()
{
    return *iter;
}

void Shape::turnStep()
{
    ++this->iter;
    if(this->iter==this->order.end())
        this->iter = this->order.begin();
}

QPoint Shape::getLeftOrder() const
{
    auto leftOrder = *(*iter).begin();
    auto curOrder = QPoint(0,0);
    for(const auto &elem:(*iter))
    {
        curOrder += elem;
        if(curOrder.x()<leftOrder.x())
            leftOrder = curOrder;
    }
    return leftOrder+this->head;
}

QPoint Shape::getRightOrder() const
{
    auto rightOrder = *(*iter).begin();
    auto curOrder = QPoint(0,0);
    for(const auto &elem:(*iter))
    {
        curOrder += elem;
        if(curOrder.x()>rightOrder.x())
            rightOrder = curOrder;
    }
    return rightOrder+this->head;
}

QPoint Shape::getUpOrder() const
{
    auto leftOrder = *(*iter).begin();
    auto curOrder = QPoint(0,0);
    for(const auto &elem:(*iter))
    {
        curOrder += elem;
        if(curOrder.y()<leftOrder.y())
            leftOrder = curOrder;
    }
    return leftOrder+this->head;
}

vector<QPoint> Shape::getDownOrderVector() const
{
    vector<QPoint> result;
    map<int, int> temp;
    auto curOrder = QPoint(0,0);
    for(const auto &elem:(*iter))
    {
        curOrder +=elem;
        auto myFinding = temp.find(curOrder.x());
        if(myFinding==temp.end())
            temp[curOrder.x()]=curOrder.y();
        else
        {
            if(myFinding->second<curOrder.y())
                myFinding->second=curOrder.y();
        }
    }
    for(const auto &elem:temp)
    {
        result.push_back(QPoint(elem.first,elem.second)+this->head);
    }
    return result;
}

vector<QPoint> Shape::getLeftOrderVector() const
{
    vector<QPoint> result;
    //y,x
    map<int, int> temp;
    auto curOrder = QPoint(0,0);
    for(const auto &elem:(*iter))
    {
        curOrder +=elem;
        auto myFinding = temp.find(curOrder.y());
        if(myFinding==temp.end())
            temp[curOrder.y()]=curOrder.x();
        else
        {
            if(myFinding->second>curOrder.x())
                myFinding->second=curOrder.x();
        }
    }
    for(const auto &elem:temp)
    {
        result.push_back(QPoint(elem.second,elem.first)+this->head);
    }
    return result;
}

vector<QPoint> Shape::getRightOrderVector() const
{
    vector<QPoint> result;
    //y,x
    map<int, int> temp;
    auto curOrder = QPoint(0,0);
    for(const auto &elem:(*iter))
    {
        curOrder +=elem;
        auto myFinding = temp.find(curOrder.y());
        if(myFinding==temp.end())
            temp[curOrder.y()]=curOrder.x();
        else
        {
            if(myFinding->second<curOrder.x())
                myFinding->second=curOrder.x();
        }
    }
    for(const auto &elem:temp)
    {
        result.push_back(QPoint(elem.second,elem.first)+this->head);
    }
    return result;
}

Shape &Shape::setHead(const QPoint &p)
{
    this->head = p;
    return *this;
}
